home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / misc / emu / msh-156.lha / han / han2.c < prev    next >
C/C++ Source or Header  |  1996-12-22  |  14KB  |  512 lines

  1. /*-
  2.  * $Id: han2.c,v 1.56 1996/12/22 00:22:33 Rhialto Rel $
  3.  *
  4.  * The code for the messydos file system handler.
  5.  *
  6.  * New functions to make 2.0+ stuff work.
  7.  *
  8.  * This code is (C) Copyright 1991-1994 by Olaf Seibert. All rights reserved.
  9.  * May not be used or copied without a licence.
  10.  *
  11.  * $Log: han2.c,v $
  12.  * Revision 1.56  1996/12/22  00:22:33  Rhialto
  13.  * Add MSSerializeDisk. Update file lock in MSSetFileSize.
  14.  *
  15.  * Revision 1.55  1993/12/30  23:28:00    Rhialto
  16.  * Freeze for MAXON5.
  17.  * Add MSFormat().
  18.  * Lots of small changes for LONGNAMES option.
  19.  * Fix MSSameLock(), because TADM was wrong again.
  20.  *
  21.  * Revision 1.54  1993/06/24  05:12:49    Rhialto
  22.  * DICE 2.07.54R.
  23.  *
  24.  * Revision 1.53  92/10/25  02:43:47  Rhialto
  25.  * Make it work.
  26.  *
  27.  * Revision 1.52  92/09/06  00:20:34  Rhialto
  28.  *
  29.  * Revision 1.46  91/10/06  18:26:04  Rhialto
  30.  *
  31.  * Freeze for MAXON
  32.  *
  33.  * Revision 1.43  91/09/28  01:30:07  Rhialto
  34.  * Preliminary - not functional yet
  35. -*/
  36.  
  37. #include "han.h"
  38. #include "dos.h"
  39. #include <string.h>
  40.  
  41. #ifdef ACTION_SAME_LOCK      /* Do we have 2.0 includes? */
  42.  
  43. #if HDEBUG
  44. #   include "syslog.h"
  45. #else
  46. #   define    debug(x)
  47. #endif
  48.  
  49. Prototype long    MSSameLock(struct MSFileLock *lock1, struct MSFileLock *lock2);
  50. Prototype struct MSFileHandle *MSOpenFromLock(struct MSFileLock *lock);
  51. Prototype struct MSFileLock *MSDupLockFromFH(struct MSFileHandle *msfh);
  52. Prototype struct MSFileLock *MSParentOfFH(struct MSFileHandle *msfh);
  53. Prototype long    MSExamineFH(struct MSFileHandle *msfh, struct FileInfoBlock *fib);
  54. Prototype long    MSSetFileSize(struct MSFileHandle *msfh, long pos, long mode);
  55. Prototype long    MSChangeModeLock(struct MSFileLock *object, long newmode);
  56. Prototype long    MSChangeModeFH(struct MSFileHandle *object, long newmode);
  57. Prototype long    MSFormat(char *vol, long type);
  58. Prototype long    MSSerializeDisk(void);
  59.  
  60. /*
  61.  * We are taking great care to share lock structures between locks on
  62.  * the same file. It is here, among other places, that we exploit that.
  63.  */
  64. long
  65. MSSameLock(lock1, lock2)
  66. struct MSFileLock *lock1, *lock2;
  67. {
  68.     return (lock1 == lock2);
  69. }
  70.  
  71. struct MSFileHandle *
  72. MSOpenFromLock(lock)
  73. struct MSFileLock *lock;
  74. {
  75.     return MakeMSFileHandle(lock, MODE_OLDFILE);
  76.     /* The lock is now owned by the MSFileHandle */
  77. }
  78.  
  79. /*
  80.  * For DupLockFromFH and ParentOfFH we force the user to insert the disk.
  81.  * This is the only easy way of knowing the VolumeNode from the filehandle,
  82.  * and we need it in the FileLock. Yech!
  83.  */
  84.  
  85. struct MSFileLock *
  86. MSDupLockFromFH(msfh)
  87. struct MSFileHandle *msfh;
  88. {
  89.     if (CheckLock(msfh->msfh_FileLock) == 0) {
  90.     debug(("MSDupLockFromFH\n"));
  91.     return MSDupLock(msfh->msfh_FileLock);
  92.     } else {
  93.     debug(("MSDupLockFromFH, fails\n"));
  94.     return NULL;
  95.     }
  96. }
  97.  
  98. struct MSFileLock *
  99. MSParentOfFH(msfh)
  100. struct MSFileHandle *msfh;
  101. {
  102.     if (CheckLock(msfh->msfh_FileLock) == 0) {
  103.     debug(("MSParentOfFH\n"));
  104.     return MSParentDir(msfh->msfh_FileLock);
  105.     } else {
  106.     debug(("MSParentOfFH, fails\n"));
  107.     return NULL;
  108.     }
  109. }
  110.  
  111. long
  112. MSExamineFH(msfh, fib)
  113. struct MSFileHandle *msfh;
  114. struct FileInfoBlock *fib;
  115. {
  116.     return MSExamine(msfh->msfh_FileLock, fib);
  117. }
  118.  
  119. /*
  120.  * MSSetFileSize.
  121.  *
  122.  * For the case that we shorten a file and invalidate existing seek pointer,
  123.  * there is a test in MSRead(), MSWrite() and MSSeek() which detects this
  124.  * condition. It is not worth (yet?) to keep a list of file handles
  125.  * so we can do the same test here.
  126.  */
  127.  
  128. long
  129. MSSetFileSize(msfh, pos, mode)
  130. struct MSFileHandle *msfh;
  131. long        pos;
  132. long        mode;
  133. {
  134.     long        oldclusters,
  135.             newclusters;
  136.     struct MSFileLock *msfl;
  137.     long        success = DOSFALSE;
  138.  
  139.     msfl = msfh->msfh_FileLock;
  140.  
  141.     if (msfl->msfl_Msd.msd_Attributes & ATTR_READONLY) {
  142.     debug(("MSSetFileSize on writeprotected file\n"));
  143.     error = ERROR_WRITE_PROTECTED;
  144.     return DOSFALSE;
  145.     }
  146.  
  147.     AdjustSeekPos(msfh);
  148.     pos = FilePos(msfh, pos, mode);
  149.  
  150.     if (pos < 0) {
  151.     error = ERROR_SEEK_ERROR;
  152.     return DOSFALSE;
  153.     }
  154.  
  155.     oldclusters = (msfl->msfl_Msd.msd_Filesize + Disk.bpc - 1) / Disk.bpc;
  156.     newclusters = (pos + Disk.bpc - 1) / Disk.bpc;
  157.  
  158.     debug(("MSSetFileSize to %ld (%ld clusters from %ld)\n",
  159.         pos, newclusters, oldclusters));
  160.     if (newclusters == oldclusters) {
  161.     /* do nothing */
  162.     } else if (newclusters > oldclusters) {
  163.     /* extend the file */
  164.     word        cluster;
  165.  
  166.     newclusters -= oldclusters;
  167.     if (newclusters > Disk.freeclusts) {
  168.         /* Make file as long as will fit on the disk */
  169.         newclusters = Disk.freeclusts;
  170.         pos = (oldclusters + newclusters) * Disk.bpc;
  171.         debug(("File growth reduced to %d clusters\n", newclusters));
  172.         error = ERROR_DISK_FULL;
  173.     }
  174.  
  175.     cluster = msfl->msfl_Msd.msd_Cluster;
  176.     debug(("Begin with cluster %d\n", cluster));
  177.  
  178.     if (oldclusters == 0 && newclusters > 0) {
  179.         cluster = FindFreeCluster(0);
  180.         debug(("  initial cluster %d\n", cluster));
  181.         msfl->msfl_Msd.msd_Cluster = cluster;
  182.         newclusters--;
  183.     }
  184.     while (newclusters > 0) {
  185.         cluster = ExtendClusterChain(cluster);
  186.         debug(("  add cluster %d\n", cluster));
  187.         newclusters--;
  188.     }
  189.     } else if (newclusters == 0) {
  190.     /* make the file empty */
  191.  
  192.     FreeClusterChain(msfl->msfl_Msd.msd_Cluster);
  193.     msfl->msfl_Msd.msd_Cluster = 0;
  194.     } else {
  195.     /* shorten the file. This may invalidate seek pointers...  */
  196.     word        cluster;
  197.  
  198.     cluster = msfl->msfl_Msd.msd_Cluster;
  199.     oldclusters = 1;
  200.     while (oldclusters < newclusters) {
  201.         cluster = NextCluster(cluster);
  202.         oldclusters++;
  203.     }
  204.     if (cluster != FAT_EOF) {
  205.         FreeClusterChain(NextCluster(cluster));
  206.         SetFatEntry(cluster, FAT_EOF);
  207.     }
  208.     }
  209.  
  210.     msfl->msfl_Msd.msd_Filesize = pos;
  211. #if CREATIONDATE_ONLY
  212.     DirtyFileLock(msfl);
  213. #else
  214.     UpdateFileLock(msfl);
  215. #endif
  216.     AdjustSeekPos(msfh);
  217.  
  218.     return DOSTRUE;
  219. }
  220.  
  221. long
  222. MSChangeModeLock(object, newmode)
  223. struct MSFileLock *object;
  224. long        newmode;
  225. {
  226.     /* We DON'T lock directories exclusively! */
  227.     if (object->msfl_Msd.msd_Attributes & ATTR_DIR)
  228.     newmode = SHARED_LOCK;
  229.  
  230.     if (newmode == EXCLUSIVE_LOCK) {
  231.     if (object->msfl_Refcount <= 1) {
  232.         object->msfl_Refcount = -1;
  233.         return DOSTRUE;
  234.     }
  235.     error = ERROR_OBJECT_IN_USE;
  236.     } else { /* SHARED_LOCK */
  237.     if (object->msfl_Refcount == -1) {
  238.         object->msfl_Refcount = 1;
  239.     }
  240.     return DOSTRUE;
  241.     }
  242.  
  243.     return DOSFALSE;
  244. }
  245.  
  246. long
  247. MSChangeModeFH(object, newmode)
  248. struct MSFileHandle *object;
  249. long        newmode;
  250. {
  251.     if (newmode == MODE_NEWFILE)
  252.     newmode = EXCLUSIVE_LOCK;
  253.     else    /* MODE_OLDFILE, MODE_READWRITE */
  254.     newmode = SHARED_LOCK;
  255.  
  256.     return MSChangeModeLock(object->msfh_FileLock, newmode);
  257. }
  258.  
  259. /*
  260.  * ExAll can conveniently be done with Examine/ExNext... at least for now.
  261.  */
  262.  
  263. #ifdef notdef
  264.  
  265. #include <dos/exall.h>
  266. long
  267. MSExAll(lock, ead, size, data, eac)
  268. struct MSFileLock  *lock;
  269. struct ExAllData   *ead;
  270. long            size;
  271. long            data;
  272. struct ExAllControl *eac;
  273. {
  274.     struct FileInfoBlock fib;
  275.     char       *next;
  276.     struct Hook    *h;
  277.     char       *end;
  278.  
  279.     eac->eac_Entries = 0;
  280.     next = ead;
  281.     h = eac->eac_MatchFunc;
  282.     end = (char *)ead + size;
  283.     if (Examine(lock, &fib)) {
  284.     while (((char *)(ead + 1) + L_8+1+L_3 + 1) <= end &&
  285.            ExNext(lock, &fib)) {
  286.         if (h) {
  287.         if (!(h->h_SubEntry(h->h_Data)))    /* ??? */
  288.             continue;
  289.         }
  290.  
  291.         if (data >= ED_NAME) {
  292.         if (data >= ED_TYPE) {
  293.             ead->ed_Type = fib.fib_DirEntryType;
  294.             if (data >= ED_SIZE) {
  295.             ead->ed_Size = fib.fib_Size;
  296.             if (data >= ED_PROTECTION) {
  297.                 ead->ed_Protection = fib.fib_Protection;
  298.                 if (data >= ED_DATE) {
  299.                 ead->ed_Days = fib.fib_Date.Days;
  300.                 ead->ed_Mins = fib.fib_Date.Mins;
  301.                 ead->ed_Ticks = fib.fib_Date.Ticks;
  302.                 if (data >= ED_COMMENT) {
  303.                     ead->ed_Comment = NULL;
  304.                     next = &ead->ed_Comment + 1;
  305.                 } else
  306.                     next = &ead->ed_Comment;
  307.                 } else
  308.                 next = &ead->ed_Protection;
  309.             } else
  310.                 next = &ead->ed_Protection;
  311.             } else
  312.             next = &ead->ed_Size;
  313.         } else
  314.             next = &ead->ed_Type;
  315.         ead->ed_Name = next;
  316.         strcpy(next, fib.fib_FileName + 1);
  317.         next += strlen(next) + 1;
  318.         } else
  319.         next = &ead->ed_Name;
  320.  
  321.         ead = (struct ExAllData *)(((long)next + 1) & ~1);
  322.         eac->eac_Entries++;
  323.     } /* while ExNext */
  324.     return 0;   /* ??? */
  325.     }
  326.     return 0;    /* ??? */
  327. }
  328.  
  329. #endif
  330.  
  331. const ulong    BootBlock[] = {
  332.     0xEB349049, 0x424D2020, 0x332E3200, 0x02020100,    /* ...IBM  3.2..... */
  333. #if 0
  334.     0x027000A0, 0x05F90300, 0x09000200, 0x00000000,
  335.     0x00000000, 0x00000000, 0x00000000, 0x0000000F,
  336.     0x00000000, 0x0100FA33, 0xC08ED0BC, 0x007C1607,
  337.     0xBB780036, 0xC5371E56, 0x1653BF2B, 0x7CB90B00,
  338.     0xFCAC2680, 0x3D007403, 0x268A05AA, 0x8AC4E2F1,
  339.     0x061F8947, 0x02C7072B, 0x7CFBCD13, 0x7267A010,
  340.     0x7C98F726, 0x167C0306, 0x1C7C0306, 0x0E7CA33F,
  341.     0x7CA3377C, 0xB82000F7, 0x26117C8B, 0x1E0B7C03,
  342.     0xC348F7F3, 0x0106377C, 0xBB0005A1, 0x3F7CE896,
  343.     0x00B80102, 0xE8AA0072, 0x198BFBB9, 0x0B00BECD,
  344.     0x7DF3A675, 0x0D8D7F20, 0xBED87DB9, 0x0B00F3A6,
  345.     0x7418BE6E, 0x7DE86100, 0x32E4CD16, 0x5E1F8F04,
  346.     0x8F4402CD, 0x19BEB77D, 0xEBEBA11C, 0x0533D2F7,
  347.     0x360B7CFE, 0xC0A23C7C, 0xA1377CA3, 0x3D7CBB00,
  348.     0x07A1377C, 0xE84000A1, 0x187C2A06, 0x3B7C4050,
  349.     0xE84E0058, 0x72CF2806, 0x3C7C760C, 0x0106377C,
  350.     0xF7260B7C, 0x03D8EBD9, 0x8A2E157C, 0x8A16FD7D,
  351.     0x8B1E3D7C, 0xEA000070, 0x00AC0AC0, 0x7422B40E,
  352.     0xBB0700CD, 0x10EBF233, 0xD2F73618, 0x7CFEC288,
  353.     0x163B7C33, 0xD2F7361A, 0x7C88162A, 0x7CA3397C,
  354.     0xC3B4028B, 0x16397CB1, 0x06D2E60A, 0x363B7C8B,
  355.     0xCA86E98A, 0x16FD7D8A, 0x362A7CCD, 0x13C30D0A,
  356.     0x4E6F6E2D, 0x53797374, 0x656D2064, 0x69736B20,    /* Non-System disk  */
  357.     0x6F722064, 0x69736B20, 0x6572726F, 0x720D0A52,    /* or disk error..R */
  358.     0x65706C61, 0x63652061, 0x6E642073, 0x7472696B,    /* eplace and strik */
  359.     0x6520616E, 0x79206B65, 0x79207768, 0x656E2072,    /* e any key when r */
  360.     0x65616479, 0x0D0A000D, 0x0A446973, 0x6B20426F,    /* eady.....Disk Bo */
  361.     0x6F742066, 0x61696C75, 0x72650D0A, 0x0049424D,    /* ot failure...IBM */
  362.     0x42494F20, 0x20434F4D, 0x49424D44, 0x4F532020,    /* BIO    COMIBMDOS   */
  363.     0x434F4D00, 0x00000000, 0x00000000, 0x00000000,    /* COM............. */
  364.     0x00000000, 0x00000000, 0x00000000, 0x000055AA,
  365. #endif
  366. };
  367.  
  368. void
  369. PutWord(byte *address, word value)
  370. {
  371.     address[0] = value;
  372.     address[1] = value >> 8;
  373. }
  374.  
  375. /*
  376.  * Format a disk. Low-level format has already been done, so we just
  377.  * write out the bootblock, FAT and root directory.
  378.  *
  379.  * We assume all default values, because there is no way to communicate
  380.  * anything special. Keep using MSH-Format for special needs.
  381.  *
  382.  * The only adjustments we make are for 40/80 tracks and DD/HD disks.
  383.  *
  384.  * fs is the device name, but is ignored and NULL for now.
  385.  * vol is the desired volume name.
  386.  * type is the (file system private) file system type, and is ignored.
  387.  */
  388.  
  389. long
  390. MSFormat(char *vol, long type)
  391. {
  392.     byte       *sec;
  393.     int         n;
  394.     int         i, j;
  395.     ULONG        success = DOSFALSE;
  396.  
  397.     CheckDriveType();
  398.     Disk = DefaultDisk;
  399.  
  400.     debug(("MSFormat: getting boot block\n"));
  401.     n = 0;
  402.     sec = EmptySec(n);
  403.     memset(sec, 0, DefaultDisk.bps);
  404.  
  405.     CopyMem(BootBlock, sec, sizeof(BootBlock));
  406.  
  407.     debug(("%d sectors on disk, %d per track\n",
  408.        DefaultDisk.nsects, DefaultDisk.spt));
  409.  
  410.       *(sec + 0x00) = 0x00;     /* Not bootable. */
  411.  
  412.     PutWord(sec + 0x0b,   DefaultDisk.bps);
  413.       *(sec + 0x0d) = DefaultDisk.spc;
  414.     PutWord(sec + 0x0e,   DefaultDisk.res);
  415.       *(sec + 0x10) = DefaultDisk.nfats;
  416.     PutWord(sec + 0x11,   DefaultDisk.ndirs);
  417.     PutWord(sec + 0x13,   DefaultDisk.nsects);
  418.       *(sec + 0x15) = DefaultDisk.media;
  419.     PutWord(sec + 0x16,   DefaultDisk.spf);
  420.     PutWord(sec + 0x18,   DefaultDisk.spt);
  421.     PutWord(sec + 0x1a,   DefaultDisk.nsides);
  422.     PutWord(sec + 0x1c,   DefaultDisk.nhid);
  423.  
  424.     MarkSecDirty(sec);
  425.     FreeSec(sec);
  426.  
  427.     /* Go to first FAT: skip bootblock. */
  428.  
  429.     n += DefaultDisk.res;
  430.  
  431.     for (i = 0; i < DefaultDisk.nfats; i++) {
  432.     debug(("MSFormat: getting first sector of FAT #%d\n", i));
  433.     sec = EmptySec(n++);
  434.     memset(sec, 0, DefaultDisk.bps);
  435.  
  436.     sec[0] = 0xF9;
  437.     sec[1] = 0xFF;
  438.     sec[2] = 0xFF;
  439.  
  440.     MarkSecDirty(sec);
  441.     FreeSec(sec);
  442.  
  443.     for (j = 1; j < DefaultDisk.spf; j++) {
  444.         debug(("MSFormat: getting sector %d of FAT #%d\n", j, i));
  445.         sec = EmptySec(n++);
  446.         memset(sec, 0, DefaultDisk.bps);
  447.         MarkSecDirty(sec);
  448.         FreeSec(sec);
  449.     }
  450.     }
  451.  
  452.     /* Clear entire root directory. */
  453.     for (i = (DefaultDisk.ndirs*MS_DIRENTSIZE + DefaultDisk.bps-1) / DefaultDisk.bps;
  454.      i > 0; i--) {
  455.     debug(("MSFormat: getting root dir sector %d\n", n));
  456.     sec = EmptySec(n++);
  457.     memset(sec, 0, DefaultDisk.bps);
  458.     MarkSecDirty(sec);
  459.     FreeSec(sec);
  460.     }
  461.  
  462.     /* Label the disk. This is ugly. */
  463.  
  464.     debug(("MSFormat: Labeling the disk\n"));
  465.     {
  466.     int        old_inhibited = Inhibited;
  467.     long        old_interleave = Interleave;
  468.  
  469.     Inhibited = 0;
  470.     Interleave &= ~NICE_TO_DFx;
  471.     MSUpdate(1);    /* Normally implied by DiskChange(), but because we
  472.              * may be Inhibit()ed, this may not happen. */
  473.     DiskChange();
  474.     if (RootLock)
  475.         success = MSRelabel(vol);
  476.     else
  477.         debug(("*** No root lock yet!\n"));
  478.     Inhibited = old_inhibited;
  479.     Interleave = old_interleave;
  480.     DiskChange();
  481.     }
  482.  
  483.     return success;
  484. }
  485.  
  486. long
  487. MSSerializeDisk(void)
  488. {
  489.     int         old_inhibited = Inhibited;
  490.     long        old_interleave = Interleave;
  491.     ULONG        success = DOSFALSE;
  492.  
  493.     Inhibited = 0;
  494.     Interleave &= ~NICE_TO_DFx;
  495.     DiskChange();
  496.     if (RootLock) {
  497.     char name[L_8 + L_3 + 1];
  498.     strncpy(name, Disk.vollabel.de_Msd.msd_Name, L_8 + L_3);
  499.  
  500.     /* Relabel with the same name... ugly. */
  501.     success = MSRelabel(name);
  502.     } else
  503.     debug(("*** No root lock yet!\n"));
  504.     Inhibited = old_inhibited;
  505.     Interleave = old_interleave;
  506.     DiskChange();
  507.  
  508.     return success;
  509. }
  510.  
  511. #endif /* ACTION_COMPARE_LOCK */
  512.